package main

/*
日志库：
	1. 支持不同的地方输出日志
	2. 日志级别：
		1. DeBug
		2. Trace
		3. Info
		4. Warning
		5. Error
		6. Fatal
	3. 日志支持开关控制
	3. 日志格式：时间 行号 文件名 日志级别 日志信息
	3. 日志文件要切割
*/
import (
	"errors"
	"fmt"
	"path"
	"runtime"
	"strings"
	"time"
)

// 创建日志级别
type logLeval uint16

const (
	UNKNOWN logLeval = iota
	DeBug
	Info
	Warning
	Error
	Fatal
)

// 定义接口
type logFun interface {
	Debug(msg string)
	Info(msg string)
	Warning(msg string)
	Error(msg string)
	Fatal(msg string)
}

// 定义结构体
type Logger struct {
	Level logLeval // 日志最高等级
}

// 构造函数
func Newlog(s string) Logger {
	Leval, err := parseLogLevel(s)
	if err != nil {
		fmt.Printf("err: %v\n", err)
	}
	return Logger{Leval}
}

// 实现方法
func (l Logger) Debug(msg string, a ...interface{}) {
	if l.enable(DeBug) {
		log(DeBug, msg, a...)
	} else {
		fmt.Printf("l.Level: %v   等级校验失败\n", l.Level)
	}
}
func (l Logger) Info(msg string) {
	if l.enable(Info) {
		log(Info, msg)
	} else {
		fmt.Printf("l.Level: %v   等级校验失败\n", l.Level)
	}
}
func (l Logger) Warning(msg string) {
	if l.enable(Warning) {
		log(Warning, msg)
	} else {
		fmt.Printf("l.Level: %v   等级校验失败\n", l.Level)
	}
}
func (l Logger) Error(msg string) {}
func (l Logger) Fatal(msg string) {}

// 解析日志级别
func parseLogLevel(s string) (logLeval, error) {
	switch strings.ToUpper(s) {
	case "DEBUG":
		{
			return DeBug, nil
		}
	case "INFO":
		{
			return Info, nil
		}
	case "WARNING":
		{
			return Warning, nil
		}
	case "ERROR":
		{
			return Error, nil
		}
	case "FATAL":
		{
			return Fatal, nil
		}
	default:
		err := errors.New("无效的日志级别")
		return UNKNOWN, err
	}
}

// 解析日志等级
func (l Logger) enable(logLeval logLeval) bool {
	return l.Level <= logLeval
}

// 解析行号
func getInfo(skip int) (string, string, int) {
	pc, file, lineNo, ok := runtime.Caller(skip)
	if !ok {
		fmt.Println("runtime.Caleveler( ) error !")
		// return
	}
	funcName := runtime.FuncForPC(pc).Name()
	fileName := path.Base(file)
	return funcName, fileName, lineNo
}

// 终端打印函数
func log(lv logLeval, msg string, a ...interface{}) {
	msg = fmt.Sprintf(msg, a...)
	tmp := a
	fmt.Printf("%T\n", tmp)
	// 获取时间
	now := time.Now()
	nowTime := now.Format("2006-01-02 15:04:05")
	// 获取调用函数 文件路径  行号
	funcName, fileName, lineNo := getInfo(3)
	// 获取等级
	var level string
	switch lv {
	case DeBug:
		{
			level = "DEBUG"
		}
	case Info:
		{
			level = "INFO"
		}
	case Warning:
		{
			level = "WARNING"
		}
	case Error:
		{
			level = "ERROR"
		}
	case Fatal:
		{
			level = "FATAL"
		}
	}
	fmt.Printf("[%v] [%s] [%s  %s:%d]  %v\n", nowTime, level, fileName, funcName, lineNo, msg)
}

func main() {
	// 测试日志库
	log := Newlog("debug")
	for {
		log.Debug("这是Debug日志信息 err:%s number:%d ", "err", 1203)
		log.Warning("这是Warring日志信息")
		log.Info("这是Info日志信息")
		time.Sleep(10 * time.Second)
	}
}
